package org.dromara.pe.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.dromara.basic.domain.FaceImage;
import org.dromara.basic.domain.bo.MemberBo;
import org.dromara.basic.domain.vo.FaceImageVo;
import org.dromara.basic.domain.vo.MemberVo;
import org.dromara.basic.service.IDictService;
import org.dromara.basic.service.IMemberService;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.pe.domain.TaskReservation;
import org.dromara.pe.domain.bo.*;
import org.dromara.pe.domain.vo.*;
import org.dromara.pe.mapper.*;
import org.dromara.pe.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.dromara.pe.domain.TaskArrangeInfo;
import org.springframework.transaction.annotation.Transactional;

import javax.print.DocFlavor;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * 预约排班管理Service业务层处理
 *
 * @author Lion Li
 * @date 2024-09-02
 */
@RequiredArgsConstructor
@Service
public class TaskArrangeInfoServiceImpl implements ITaskArrangeInfoService {

    private final TaskArrangeInfoMapper baseMapper;


    private final ITaskReservationService taskReservationService;

    private final IMemberService memberService;

    private final IScopeSettingService scopeSettingService;

    private final IAchievementService achievementService;

    private final TaskReservationMapper taskReservationMapper;
    private final ITaskInfoService taskInfoService;

    private final IDictService dictService;

    @Autowired
    @Qualifier("globalThreadPool")
    private ExecutorService globalThreadPool;
    /**
     * 查询预约排班管理
     */
    @Override
    public TaskArrangeInfoVo queryById(Long arrangeId) {
        return baseMapper.selectVoById(arrangeId);
    }

    /**
     * 查询预约排班管理列表
     */
    @Override
    public TableDataInfo<TaskArrangeInfoVo> queryPageList(TaskArrangeInfoBo bo, PageQuery pageQuery) {
        QueryWrapper<TaskArrangeInfo> lqw = buildQueryWrapper(bo);
        Page<TaskArrangeInfoVo> result = baseMapper.selectTaskArrangeInfoList(pageQuery.build(), lqw);
        this.selectData(result);
        return TableDataInfo.build(result);
    }

    public TableDataInfo<TaskArrangeInfoVo> queryPageListReview(TaskArrangeInfoBo bo, PageQuery pageQuery) {
        QueryWrapper<TaskArrangeInfo> lqw = buildQueryWrapper(bo);
        Page<TaskArrangeInfoVo> result = baseMapper.selectTaskArrangeInfoReviewList(pageQuery.build(), lqw);
        this.selectData(result);
        return TableDataInfo.build(result);
    }

    /**
     * 查询预约排班管理列表
     */
    @Override
    public List<TaskArrangeInfoVo> queryList(TaskArrangeInfoBo bo) {
        QueryWrapper<TaskArrangeInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectTaskArrangeInfoList(lqw);
    }

    private void selectData(Page<TaskArrangeInfoVo> result) {
        List<TaskArrangeInfoVo> records = result.getRecords();
        for (TaskArrangeInfoVo taskArrangeInfoVo : records) {
            String scopeId = taskArrangeInfoVo.getScopeIds();
            if (StringUtils.isNotEmpty(scopeId)) {
                List<Long> scopeIds = Arrays.stream(scopeId.split(",")).map(Long::parseLong).collect(Collectors.toList());
                ScopeSettingBo scopeSettingBo = new ScopeSettingBo();
                scopeSettingBo.setScopeIds(scopeIds);
                List<ScopeSettingVo> scopeSettingVos = scopeSettingService.queryList(scopeSettingBo);
                taskArrangeInfoVo.setScopeSettingVos(scopeSettingVos);
            }

        }
    }

    private QueryWrapper<TaskArrangeInfo> buildQueryWrapper(TaskArrangeInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<TaskArrangeInfo> lqw = new QueryWrapper<>();
        lqw.eq(bo.getTaskId() != null, "petai.task_id", bo.getTaskId());
        lqw.eq(bo.getClassId() != null, "petai.class_id", bo.getClassId());
        lqw.like(StringUtils.isNotBlank(bo.getArrangeName()), "petai.arrange_name", bo.getArrangeName());
        lqw.like(StringUtils.isNotBlank(bo.getTaskName()), "peti.task_name", bo.getTaskName());
        lqw.eq(bo.getAreaId() != null, "petai.area_id", bo.getAreaId());
        lqw.like(StringUtils.isNotBlank(bo.getAreaName()), "petai.area_name", bo.getAreaName());
        lqw.eq(bo.getScopeTypeId() != null, "petai.scope_type_id", bo.getScopeTypeId());
        lqw.like(StringUtils.isNotBlank(bo.getScopeTypeName()), "petai.scope_type_name", bo.getScopeTypeName());
        lqw.eq(StringUtils.isNotBlank(bo.getSexLimit()), "petai.sex_limit", bo.getSexLimit());
        lqw.eq(StringUtils.isNotBlank(bo.getIsEnable()), "petai.is_enable", bo.getIsEnable());
        return lqw;
    }

    /**
     * 新增预约排班管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(TaskArrangeInfoBo bo) throws ParseException {
        this.tranData(bo);
        TaskArrangeInfo add = MapstructUtils.convert(bo, TaskArrangeInfo.class);
//        validEntityBeforeSave(bo);
        boolean flag = baseMapper.insert(add) > 0;
        if (!flag) {
            throw new ServiceException("生成排班失败");
        }

        // 设置 bo 的排班 ID 为刚插入的数据 ID
        bo.setArrangeId(add.getArrangeId());
        if (ObjectUtils.isNotEmpty(bo.getClassId())) {
            AchievementBo achievementBo=new AchievementBo();
            TaskInfoVo taskInfoVo = taskInfoService.queryById(bo.getTaskId());
            if(ObjectUtils.isNotEmpty(taskInfoVo)){
                achievementBo.setSemester(taskInfoVo.getSemester());
                achievementBo.setAcademicYear(taskInfoVo.getAcademicYear());
            }
            achievementBo.setTaskId(bo.getTaskId());
            achievementBo.setClassId(bo.getClassId());
            List<AchievementVo> achievementVos = achievementService.queryList(achievementBo);
            if(CollectionUtils.isEmpty(achievementVos)){
                // 调用生成体测成绩的方法
                List<String> stuNums = getStudentNumbersForClass(bo.getClassId());
                Long taskId = bo.getTaskId();
                if (!achievementService.insertAchievementsByTask(taskId, stuNums,achievementBo.getAcademicYear(),achievementBo.getSemester())) {
                    throw new ServiceException("生成排班失败");
                }
            }
            this.buildTaskReservation(bo);
            Long status=0L;
            if(status.equals(taskInfoVo.getTaskStatus())){
                TaskInfoBo taskInfoBo=new TaskInfoBo();
                taskInfoBo.setTaskId(taskInfoVo.getTaskId());
                taskInfoBo.setTaskStatus(1L);
                Boolean b = taskInfoService.updateByBo(taskInfoBo);
                if (!b) {
                    throw new ServiceException("生成排班失败");
                }
            }
        }
        return true;
    }

    // 一个辅助方法，用于获取班级的学生学号列表
    private List<String> getStudentNumbersForClass(Long classId) {
        MemberBo memberBo = new MemberBo();
        memberBo.setClassId(classId);
        List<MemberVo> students = memberService.queryList(memberBo);
        return students.stream().map(MemberVo::getIdNumber).collect(Collectors.toList());
    }


    /**
     * 修改预约排班管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(TaskArrangeInfoBo bo) throws ParseException {
        this.tranData(bo);
        TaskArrangeInfo update = MapstructUtils.convert(bo, TaskArrangeInfo.class);
        TaskArrangeInfoVo taskArrangeInfoVo = baseMapper.selectVoById(bo.getArrangeId());
//        TaskArrangeInfoVo taskArrangeInfoVo = baseMapper.selectVoById(bo.getArrangeId());
        boolean flag = baseMapper.updateById(update) > 0;
        if (!flag) {
            throw new ServiceException("更新预约排班失败");
        }
//        if(ObjectUtils.isNotEmpty(taskArrangeInfoVo)&&bo.getClassId()!=null){
//            if(taskArrangeInfoVo.getClassId()!=bo.getClassId()){
//                if(taskArrangeInfoVo.getTaskId()!=null){
//                    Boolean aBoolean = achievementService.deleteAchievementByBatch(taskArrangeInfoVo.getTaskId());
//                    if (!aBoolean) {
//                        throw new ServiceException("删除失败");
//                    }
//                }
//                if (ObjectUtils.isNotEmpty(bo.getClassId())) {
//                    // 调用生成体测成绩的方法
//                    List<String> stuNums = getStudentNumbersForClass(bo.getClassId());
//                    Long taskId = bo.getTaskId();
//                    if (!achievementService.insertAchievementsByTask(taskId, stuNums)) {
//                        throw new ServiceException("生成排班失败");
//                    }
//                }
//            }
//        }

//        if (ObjectUtils.isNotEmpty(taskArrangeInfoVo)) {
//            if(bo.getClassId()!=null&&!taskArrangeInfoVo.getClassId().equals(bo.getClassId())){
//                TaskReservationBo taskReservation = new TaskReservationBo();
//                taskReservation.setTaskId(bo.getTaskId());
//                taskReservation.setArrangeId(bo.getArrangeId());
//                Boolean aBoolean = taskReservationService.batchDelete(taskReservation);
//                if (!aBoolean) {
//                    throw new ServiceException("删除预约名单失败");
//                }
//                this.buildTaskReservation(bo);
//            }
//        }
        //validEntityBeforeSave(bo);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public void buildTaskReservation(TaskArrangeInfoBo bo) {
        Long classId = bo.getClassId(); //获取classid
        MemberBo memberBo = new MemberBo();
        memberBo.setClassId(classId);
        if (!"2".equals(bo.getSexLimit()) && ("1".equals(bo.getSexLimit()) || "0".equals(bo.getSexLimit()))) {
            memberBo.setGender(bo.getSexLimit());
        }
        List<MemberVo> studentList = memberService.queryList(memberBo);
        if (CollectionUtils.isEmpty(studentList)) {
            throw new ServiceException("查询不到学生，生成排班失败");
        }
        // 使用线程安全的队列来存储 FaceImage 对象
        Queue<TaskReservation> faceImagesQueue = new ConcurrentLinkedQueue<>();
        List<Future<?>> futures = new ArrayList<>();

        // 为每个学生信息创建一个线程任务
        for (MemberVo memberVo : studentList) {
            TaskReservationBo taskReservationBo = new TaskReservationBo();
            taskReservationBo.setTaskId(bo.getTaskId());
            taskReservationBo.setStuNum(memberVo.getIdNumber());
            List<TaskReservationVo> taskReservationVos = taskReservationService.queryList(taskReservationBo);
            if(CollectionUtils.isNotEmpty(taskReservationVos)){
                continue;
            }
            Runnable task = () -> {
                TaskReservation taskReservation = new TaskReservation();
                taskReservation.setTaskId(bo.getTaskId());
                taskReservation.setArrangeId(bo.getArrangeId());
                taskReservation.setStuNum(memberVo.getIdNumber());
                taskReservation.setClassId(memberVo.getClassId());
                taskReservation.setGrade(memberVo.getGrade());
                faceImagesQueue.add(taskReservation);
            };
            // 提交任务到线程池
            Future<?> future = globalThreadPool.submit(task);
            futures.add(future);
        }

        // 等待所有任务完成
        for (Future<?> future : futures) {
            try {
                future.get(); // 阻塞，直到任务执行完成
            } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        // 将所有收集到的 FaceImage 对象插入数据库
        if (!faceImagesQueue.isEmpty()) {
            Boolean insertResult = taskReservationMapper.insertBatch(new ArrayList<>(faceImagesQueue));
            if (!insertResult) {
                throw new ServiceException("生成预约名单失败");
            }
        }
    }

    private void tranData(TaskArrangeInfoBo bo) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, Object> params = bo.getParams();
        if (params.get("beginArrangeDate") != null) {
            String s = params.get("beginArrangeDate").toString();
            Date parse = dateFormat.parse(s);
            bo.setStartArrangeDate(parse);
        }
        if (params.get("endArrangeDate") != null) {
            String s = params.get("endArrangeDate").toString();
            Date parse = dateFormat.parse(s);
            bo.setEndArrangeDate(parse);
        }
        if (params.get("beginArrangeTime") != null) {
            String s = params.get("beginArrangeTime").toString();
            Time parse = Time.valueOf(s);
            bo.setStartArrangeTime(parse);
        }
        if (params.get("endArrangeTime") != null) {
            String s = params.get("endArrangeTime").toString();
            Time parse = Time.valueOf(s);
            bo.setEndArrangeTime(parse);
        }

    }


    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TaskArrangeInfoBo entity) {
        List<TaskArrangeInfoVo> taskArrangeInfoVoList = baseMapper.selectTaskArrangeInfoBoList(entity);
        String TaskNames = "";
        if (taskArrangeInfoVoList != null && taskArrangeInfoVoList.size() > 0) {
            for (TaskArrangeInfoVo info : taskArrangeInfoVoList) {
                String ScopeIds = info.getScopeIds();
                String[] scopeIds = entity.getScopeIds().split(",");
                for (String index : scopeIds) { //判断是否有重复的项目集合
                    if (ScopeIds.indexOf(index) > 0) {
                        TaskNames += info.getArrangeName() + "|";
                    }
                }

            }
            if (!"".equals(TaskNames)) {
                throw new ServiceException("存在重复排班,排班名称为：" + TaskNames);

            }
        }

    }

    /**
     * 批量删除预约排班管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        Long taskId=null;
        for (Long id : ids) {
            TaskArrangeInfoVo taskArrangeInfoVo = baseMapper.selectVoById(id);
            if (ObjectUtils.isNotEmpty(taskArrangeInfoVo)) {
                if(taskArrangeInfoVo.getTaskId()!=null){
                    taskId=taskArrangeInfoVo.getTaskId();
                    QueryWrapper<TaskReservation> taskReservationQueryWrapper=new QueryWrapper<>();
                    taskReservationQueryWrapper.eq(taskArrangeInfoVo.getTaskId()!=null,"task_id",taskArrangeInfoVo.getTaskId());
                    taskReservationQueryWrapper.eq(taskArrangeInfoVo.getArrangeId()!=null,"arrange_id",taskArrangeInfoVo.getArrangeId());
                    Boolean aBoolean = taskReservationMapper.delete(taskReservationQueryWrapper)>0;
                    if (!aBoolean) {
                        throw new ServiceException("删除失败");
                    }
                }
            }
        }
        boolean b = baseMapper.deleteBatchIds(ids) > 0;
        if(!b){
            throw new ServiceException("删除失败");
        }
        TaskArrangeInfoBo taskArrangeInfoBo=new TaskArrangeInfoBo();
        taskArrangeInfoBo.setTaskId(taskId);
        List<TaskArrangeInfoVo> taskArrangeInfoVos = this.queryList(taskArrangeInfoBo);
        if(CollectionUtils.isEmpty(taskArrangeInfoVos)){
            TaskInfoBo taskInfoBo=new TaskInfoBo();
            taskInfoBo.setTaskId(taskId);
            taskInfoBo.setTaskStatus(0L);
            Boolean b1 = taskInfoService.updateByBo(taskInfoBo);
            if (!b1) {
                throw new ServiceException("删除失败");
            }
        }
        return true;
    }

    @Override
    public Boolean updateValidByIds(List<Long> statusByIds, String status, boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        baseMapper.updateValidByIds(statusByIds, status);
        // return baseMapper.updateAuditStatusByYes(ids) > 0;
        return true;
    }
}
